package cn.keniykey.mc.landterritory.database;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;

import cn.keniykey.mc.landterritory.LandTerritoryMain;
import cn.keniykey.mc.landterritory.toolkit.DebugUtil;

public final class SqliteCore extends AbDataBase{
	private Connection con;
	private File file;
	private volatile Thread thread;
	private volatile LinkedList<DataRepository> links;
	//
	SqliteCore(File file) throws ClassNotFoundException {
		Class.forName("org.sqlite.JDBC");
		this.file = file;
		this.links = new LinkedList<>();
	}
	@Override
	public Connection getConnection() {
		try {
			if(this.con != null && !this.con.isClosed()) return this.con;
		}catch(SQLException ex) {
			LandTerritoryMain.getPlugin().getLogger().warning("判断数据库连接[SqliteCore]错误");
			ex.printStackTrace();
		}
		try {
			if(!this.file.exists()) this.file.createNewFile();
			return this.con = DriverManager.getConnection("jdbc:sqlite:" + this.file.toString());
		}catch(SQLException | IOException ex) {
			LandTerritoryMain.getPlugin().getLogger().warning("获取数据库连接[SqliteCore]报错");
			ex.printStackTrace();
		}
		return null;
	}
	@Override
	public void update(String sql, Object... objs) {
		synchronized (this.links) {
			this.links.add(new DataRepository(sql, objs));
		}
		DebugUtil.info("[SqliteCore]数据队列中已加入新数据");
		if (this.thread == null || !this.thread.isAlive()) {
			this.thread = new DataBaseThread();
			this.thread.start();
		}
	}
	private final class DataBaseThread extends Thread {
		DataBaseThread() {}
		public void run() {
			try {
				DebugUtil.info("[SqliteCore]数据队列清空线程启动");
				Thread.sleep(10000L);
			} catch (Exception ex) {
				LandTerritoryMain.getPlugin().getLogger().warning("[SqliteCore]无法完成线程休眠延时等待");
				ex.printStackTrace();
			}
			SqliteCore.this.fush();
		}
	}
	@Override
	public synchronized void fush() {
		DebugUtil.info("[SqliteCore]数据队列开始清空");
		while(!this.links.isEmpty()) {
			final DataRepository dr;
			synchronized (this.links) {
				dr = this.links.removeFirst();
			}
			try{
				this.excute(dr.getSQL(), dr.getValues());
			}catch(Exception ex) {
				LandTerritoryMain.getPlugin().getLogger().warning("[SqliteCore]数据库fush无法执行指令：" + dr.toString());
				ex.printStackTrace();
			}
		}
		DebugUtil.info("数据队列[SqliteCore]清空结束");
	}
	@Override
	public void excute(String sql, Object... objs) throws SQLException {
		final PreparedStatement ps;
		try {
			ps = this.getConnection().prepareStatement(sql);
		}catch(Exception ex) {
			LandTerritoryMain.getPlugin().getLogger().warning("[SqliteCore]数据库无法获取PrepareStatement：" + sql);
			ex.printStackTrace();
			return;
		}
		try {
			if(objs != null && objs.length > 0) AbDataBase.setParameters(ps, objs);
			ps.execute();
		}finally {
			try{
				ps.close();
			}catch(Exception ex) {
				LandTerritoryMain.getPlugin().getLogger().warning("[SqliteCore]数据库无法关闭PrepareStatement");
				DebugUtil.info(ex);;
			}
		}
	}
	@Override
	public ResultSet query(String sql, Object... objs) throws SQLException {
		final PreparedStatement ps = this.getConnection().prepareStatement(sql);
		if(objs != null && objs.length > 0) AbDataBase.setParameters(ps, objs);
		return ps.executeQuery();
	}
	@Override
	protected void close() {
		try {
			if (this.con != null && !this.con.isClosed()) {
				this.fush();
				DebugUtil.info("[SqliteCore]数据库已完成等待数据队列净空");
				this.con.close();
				DebugUtil.info("[SqliteCore]数据库关闭成功");
				this.con = null;
			}
		} catch (SQLException ex) {
			LandTerritoryMain.getPlugin().getLogger().warning("[SqliteCore]数据库关闭异常");
			ex.printStackTrace();
		}
	}
	@Override
	public String toString() {
		return "Sqlite";
	}
}